package com.jl;

import com.jl.annotate.Factory;
import com.jl.annotate.FactoryRoute;
import com.jl.set.map.JHashMap;
import com.jl.set.map.JMap;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
@RequiredArgsConstructor
public class FactoryUtils {

    private final ApplicationContext appContext;

    private static JMap<String, JMap<String, Object>> serviceJMap = new JHashMap<>();

    private static JMap<String, RouteService> routeServiceJMap = new JHashMap<>();

    @PostConstruct
    public void getFactorys() {
        String[] beans = appContext.getBeanDefinitionNames();
        for (String bean : beans) {
            try {
                Object beanObj = appContext.getBean(bean);
                Class<?> clazz = beanObj.getClass();
                if (clazz.isAnnotationPresent(Factory.class)) {
                    Factory factory = clazz.getAnnotation(Factory.class);
                    Class<?> anInterface = clazz.getInterfaces()[0];
                    String name = anInterface.getName();
                    String type = factory.type();
                    if (serviceJMap.containsKey(name)) {
                        serviceJMap.get(name).set(type, beanObj);
                    } else {
                        JMap<String, Object> map = new JHashMap<String, Object>()
                                .set(type, beanObj);
                        serviceJMap.put(name, map);
                    }
                }
                if (clazz.isAnnotationPresent(FactoryRoute.class)) {
                    FactoryRoute factoryRoute = clazz.getAnnotation(FactoryRoute.class);
                    Class anInterface = factoryRoute.interfaceClass();
                    String name = anInterface.getName();
                    RouteService value = (RouteService) beanObj;
                    routeServiceJMap.put(name, value);
                }
            } catch (Exception e) {

            }
        }
    }

    /**
     * 获取工厂bean
     *
     * @param serviceClass 工厂接口
     * @param value        匹配值
     * @param <T>
     * @return
     */
    public static <T> T getService(Class<T> serviceClass, Object value) {
        JMap<String, Object> map = serviceJMap.get(serviceClass.getName());
        return (T) map.get(value.toString());
    }

    /**
     * 获取工厂bean
     *
     * @param serviceClass 工厂接口
     * @param value        匹配值
     * @param <T>
     * @return
     */
    public static <T> T getService(Class<T> serviceClass, FunctionUtils.NoParamsResult value) {
        return getService(serviceClass, value.run());
    }

    /**
     * 获取工厂bean（路由）
     *
     * @param serviceClass 工厂接口
     * @param roteValue    路由参数
     * @param <T>
     * @return
     */
    public static <T> T getServiceRoute(Class<T> serviceClass, Object roteValue) {
        RouteService routeService = routeServiceJMap.get(serviceClass.getName());
        String value = routeService.route(roteValue);
        return getService(serviceClass, value);
    }

    /**
     * 获取工厂bean（路由）
     *
     * @param serviceClass 工厂接口
     * @param roteValue    路由参数
     * @param <T>
     * @return
     */
    public static <T> T getServiceRoute(Class<T> serviceClass, FunctionUtils.NoParamsResult roteValue) {
        return getServiceRoute(serviceClass, roteValue.run());
    }

    public interface RouteService {

        /**
         * 路由
         *
         * @return 匹配值
         */
        String route(Object object);

    }
}
